package com.sunwayworld.basemodule.samplemanage.sample.service.impl;

import com.sunwayworld.basemodule.basedata.sampletype.bean.LimsSampleTypeBean;
import com.sunwayworld.basemodule.basedata.sampletype.service.LimsSampleTypeService;
import com.sunwayworld.basemodule.business.batch.bean.LimsBatchSampleBean;
import com.sunwayworld.basemodule.business.ordertask.bean.LimsOrderTaskBean;
import com.sunwayworld.basemodule.business.ordertask.service.LimsOrderTaskService;
import com.sunwayworld.basemodule.samplemanage.sample.bean.DerivativeDTO;
import com.sunwayworld.basemodule.samplemanage.sample.bean.LimsSampleBean;
import com.sunwayworld.basemodule.samplemanage.sample.bean.LimsSampleDerivativeBean;
import com.sunwayworld.basemodule.samplemanage.sample.dao.LimsSampleDerivativeDao;
import com.sunwayworld.basemodule.samplemanage.sample.service.LimsSampleDerivativeService;
import com.sunwayworld.basemodule.samplemanage.sample.service.LimsSampleService;
import com.sunwayworld.framework.at.annotation.AuditTrailEntry;
import com.sunwayworld.framework.at.annotation.AuditTrailType;
import com.sunwayworld.framework.constant.Constant;
import com.sunwayworld.framework.context.ApplicationContextHelper;
import com.sunwayworld.framework.context.LocalContextHelper;
import com.sunwayworld.framework.data.page.Page;
import com.sunwayworld.framework.exception.InvalidDataException;
import com.sunwayworld.framework.i18n.I18nHelper;
import com.sunwayworld.framework.mybatis.mapper.MapperParameter;
import com.sunwayworld.framework.mybatis.mapper.MatchPattern;
import com.sunwayworld.framework.mybatis.mapper.SearchFilter;
import com.sunwayworld.framework.mybatis.page.MybatisPageHelper;
import com.sunwayworld.framework.mybatis.page.PageRowBounds;
import com.sunwayworld.framework.restful.data.RestJsonWrapperBean;
import com.sunwayworld.framework.spring.annotation.GikamBean;
import com.sunwayworld.framework.support.PersistableHelper;
import com.sunwayworld.framework.utils.CollectionUtils;
import com.sunwayworld.framework.utils.NumberUtils;
import com.sunwayworld.framework.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Repository
@GikamBean
public class LimsSampleDerivativeServiceImpl implements LimsSampleDerivativeService {

    @Autowired
    private LimsSampleDerivativeDao limsSampleDerivativeDao;

    @Lazy
    @Autowired
    private LimsSampleService sampleService;

    @Lazy
    @Autowired
    private LimsOrderTaskService orderTaskService;

    @Autowired
    @Lazy
    private LimsSampleTypeService limsSampleTypeService;

    @Override
    @SuppressWarnings("unchecked")
    public LimsSampleDerivativeDao getDao() {
        return limsSampleDerivativeDao;
    }

    @Override
    @Transactional
    @AuditTrailEntry(AuditTrailType.INSERT)
    public Long insert(RestJsonWrapperBean jsonWrapper) {
        LimsSampleDerivativeBean limsSampleDerivative = jsonWrapper.parseUnique(LimsSampleDerivativeBean.class);
        limsSampleDerivative.setId(ApplicationContextHelper.getNextIdentity());
        getDao().insert(limsSampleDerivative);
        return limsSampleDerivative.getId();
    }

    @Override
    public Page<LimsSampleBean> selectDerivativeInRunPagination(Long runId, RestJsonWrapperBean wrapperBean) {
        MapperParameter parameter = wrapperBean.extractMapFilter();
        parameter.put("runId", runId);
        PageRowBounds pageRowBounds = wrapperBean.extractPageRowBounds();
        return MybatisPageHelper.get(pageRowBounds, () -> getDao().selectDerivativeList(parameter)
                .parallelStream().map(e -> PersistableHelper.mapToPersistable(e, LimsSampleBean.class))
                .collect(Collectors.toList()));
    }

    @Override
    public Page<LimsSampleBean> selectDerivativeInTaskPagination(Long taskId, RestJsonWrapperBean wrapperBean) {
        MapperParameter parameter = wrapperBean.extractMapFilter();
        parameter.put("taskId", taskId);
        PageRowBounds pageRowBounds = wrapperBean.extractPageRowBounds();
        return MybatisPageHelper.get(pageRowBounds, () -> getDao().selectDerivativeList(parameter)
                .parallelStream().map(e -> PersistableHelper.mapToPersistable(e, LimsSampleBean.class))
                .collect(Collectors.toList()));
    }

    @Transactional
    @Override
    public void delete(RestJsonWrapperBean wrapper) {
        List<Long> ids = wrapper.parseId(Long.class);
        if (!CollectionUtils.isEmpty(ids)) {
            sampleService.getDao().deleteByIdList(ids);
            List<LimsSampleDerivativeBean> derivativeBeans = ids.stream().map(i -> {
                LimsSampleDerivativeBean derivativeBean = new LimsSampleDerivativeBean();
                derivativeBean.setDerivativeId(i);
                return derivativeBean;
            }).collect(Collectors.toList());
            getDao().deleteBy(derivativeBeans, "derivativeId");
        }
    }

    @Override
    @Transactional
    public void insertDerivative(RestJsonWrapperBean wrapper) {
        Map<String, String> parameter = wrapper.getParamMap();
        List<LimsOrderTaskBean> orderTaskList = wrapper.parse(LimsOrderTaskBean.class);
        if (orderTaskList.isEmpty()) {
            return;
        }
        List<Long> parallelIds = orderTaskList.parallelStream().map(LimsOrderTaskBean::getParallelId).collect(Collectors.toList());
        MapperParameter temp = new MapperParameter();
        temp.setFilter(SearchFilter.instance().match("parallelId", parallelIds).filter(MatchPattern.OR));
        List<LimsOrderTaskBean> orderTaskBeans = orderTaskService.selectList(temp);
        List<LimsSampleTypeBean> sampleTypeAll = limsSampleTypeService.selectAll();

        AtomicReference<String> sampleType = new AtomicReference<>(parameter.get("sampleType"));
        String sampleTypeCode = parameter.get("sampleType");
        String derivativeType = parameter.get("derivativeType");
        if (!StringUtils.isBlank(sampleTypeCode)) {
            sampleTypeAll.stream().filter(st -> st.getSampleTypeCode().equals(sampleTypeCode)).findAny().ifPresent(st -> {
                sampleType.set(st.getSampleTypeName());
            });
        }
        LimsSampleTypeBean typeBean = sampleTypeAll.stream().filter(t -> t.getSampleTypeCode().equals(sampleTypeCode)).findFirst().get();
//        LimsSampleTypeBean sampleTypeBean = sampleTypeService.selectFirstByFilter(SearchFilter.instance().match("sampleTypeCode", sampleType).filter(MatchPattern.EQ));
//        String sampleTypeName = sampleTypeBean.getSampleTypeName();
//        String briefCode = sampleTypeBean.getBriefCode();
//        if (StringUtils.isEmpty(briefCode)){//样本类型简码
//            throw new InvalidDataException(I18nHelper.getMessage("NOT.FOUND.SAMPLE.BRIEFCODE")+"【"+sampleTypeName+"】");
//        }
        String useFlg = Constant.YES;
//        List<Long> orderTaskIdList = orderTaskBeans.stream().map(LimsOrderTaskBean::getId).collect(Collectors.toList());
        // 原有衍生物，则新衍生物不启用
//        List<LimsSampleDerivativeBean> sampleDerivativeList = selectListByFilter(SearchFilter.instance().match("ORDERTASKID", orderTaskIdList).filter(MatchPattern.OR));
//        if (!sampleDerivativeList.isEmpty()) {
//            useFlg = Constant.NO;
//        }
        List<String> sampleCodeList = orderTaskBeans.stream().map(LimsOrderTaskBean::getSampleCode).distinct().collect(Collectors.toList());

        ArrayList<LimsSampleBean> insertSampleList = new ArrayList<>();
        ArrayList<LimsSampleDerivativeBean> insertSampleDerivativeList = new ArrayList<>();
        List<Long> parallelIdList = new ArrayList<>();
        if ("derivative".equalsIgnoreCase(derivativeType)) { // 衍生物
            List<LimsSampleDerivativeBean> derivativeBeansAll = this.selectListByFilter(SearchFilter.instance().match("sampleTypeCode", sampleTypeCode).filter(MatchPattern.EQ));

            for (LimsOrderTaskBean orderTaskBean : orderTaskBeans) {

                String startSampleCode = orderTaskBean.getSampleCode();

                if (!insertSampleDerivativeList.isEmpty()) {
                    parallelIdList = insertSampleDerivativeList.stream().map(m -> NumberUtils.parseLong(m.getExt$Item("parallelId"))).distinct().collect(Collectors.toList());
                }

                String derivaSampleCode = null;
                if (parallelIdList.contains(orderTaskBean.getParallelId())) {
                    //TODO 并行id相同的task 即为混样后任务  生成衍生物时公用一个衍生物编号，共用一个样本的id
//                    derivaSampleCode = insertSampleDerivativeList.stream().filter(f -> orderTaskBean.getParallelId().equals(Long.parseLong(f.getExt$Item("parallelId")))).findFirst().get().getDerivativeNo();
                    insertSampleDerivativeList.stream().filter(f -> orderTaskBean.getParallelId().equals(Long.parseLong(f.getExt$Item("parallelId")))).findFirst().ifPresent(d -> {
                        //衍生物关系表
                        LimsSampleDerivativeBean sampleDerivativeBean = new LimsSampleDerivativeBean();
                        sampleDerivativeBean.setId(ApplicationContextHelper.getNextIdentity());
                        sampleDerivativeBean.setDerivativeId(d.getDerivativeId());
                        sampleDerivativeBean.setDerivativeNo(d.getDerivativeNo());
                        sampleDerivativeBean.setParentNo(orderTaskBean.getSampleCode());
                        sampleDerivativeBean.setParentId(orderTaskBean.getSampleId());
                        sampleDerivativeBean.setOrderTaskId(orderTaskBean.getId());
                        sampleDerivativeBean.setFolderId(orderTaskBean.getFolderId());
                        sampleDerivativeBean.setOrderId(orderTaskBean.getOrderId());
                        sampleDerivativeBean.setDerivativeType(derivativeType);
                        sampleDerivativeBean.setUseFlag(useFlg);
                        sampleDerivativeBean.setExt$Item("parallelId", orderTaskBean.getParallelId().toString());
                        sampleDerivativeBean.setOriNo(orderTaskBean.getExt$Item("oriNo"));

                        //衍生物表
                        insertSampleDerivativeList.add(sampleDerivativeBean);
                    });
                } else {
                    //衍生物首字母同父样本  包含混样样本M、质控样本N,P等
                    String firstCode = startSampleCode.substring(0, 1);

                    String[] parts = startSampleCode.split("-");
                    String sampleCodeFront = "";

                    String qcsampleflg = orderTaskBean.getExt$Item("qcsampleflg");

                    if (StringUtils.isBlank(qcsampleflg) || !"1".equals(qcsampleflg)) {
                        if (parts.length > 1) {
                            List<Character> numbers = Arrays.asList('0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
                            AtomicInteger index_1 = new AtomicInteger(3);
                            for (int j = 0; j < startSampleCode.length(); j++) {
                                char c = startSampleCode.charAt(j);
                                if (numbers.stream().anyMatch(n -> n.equals(c))) {
                                    index_1.getAndSet(j);
                                    break;
                                }
                            }
                            sampleCodeFront = String.format("%s%s%s", firstCode, typeBean.getBriefCode(), parts[0].substring(index_1.get(), parts[0].length()));
                        } else {
                            sampleCodeFront = String.format("%s%s%s", firstCode, typeBean.getBriefCode(), parts[0].substring(1, parts[0].length()));
                        }
                    } else {
                        String qcBriefCode = parts[0].substring(0, 1);
                        if (parts.length > 1) {
                            List<Character> numbers = Arrays.asList('0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
                            AtomicInteger index_1 = new AtomicInteger(3);
                            for (int j = 0; j < startSampleCode.length(); j++) {
                                char c = startSampleCode.charAt(j);
                                if (numbers.stream().anyMatch(n -> n.equals(c))) {
                                    index_1.getAndSet(j);
                                    break;
                                }
                            }
                            sampleCodeFront = String.format("%s%s%s", qcBriefCode, typeBean.getBriefCode(), parts[0].substring(index_1.get(), parts[0].length()));
                        } else {
                            sampleCodeFront = String.format("%s%s%s", qcBriefCode, typeBean.getBriefCode(), parts[0].substring(1, parts[0].length()));
                        }
                    }
                    String finalSampleCodeFront = sampleCodeFront;
                    List<LimsSampleDerivativeBean> derivativeBeans = derivativeBeansAll.stream().filter(d -> !StringUtils.isBlank(d.getDerivativeNo()) && d.getDerivativeNo().contains(finalSampleCodeFront)).collect(Collectors.toList());
                    if (derivativeBeans.isEmpty()) {
                        derivaSampleCode = sampleCodeFront + "-1";
                        int max = 1;
                        boolean flag = true;
                        while (flag) {
                            boolean find = false;
                            for (LimsSampleBean s : insertSampleList) {
                                if (s.getSampleCode().equals(derivaSampleCode)) {
                                    max++;
                                    derivaSampleCode = sampleCodeFront + "-" + max;
                                    find = true;
                                    break;
                                }
                            }
                            if (!find) {
                                flag = false;
                            }
                        }
                    } else {
                        int max = 1;
                        for (LimsSampleDerivativeBean d : derivativeBeans) {
                            String derivativeNo = d.getDerivativeNo();
                            String[] parts_2 = derivativeNo.split("-");
                            if (parts_2.length > 1 && Integer.parseInt(parts_2[1]) > max) {
                                max = Integer.parseInt(parts_2[1]);
                            }
                        }
                        max++;
                        derivaSampleCode = sampleCodeFront + "-" + max;
                        boolean flag = true;
                        while (flag) {
                            boolean find = false;
                            for (LimsSampleBean s : insertSampleList) {
                                if (s.getSampleCode().equals(derivaSampleCode)) {
                                    max++;
                                    derivaSampleCode = sampleCodeFront + "-" + max;
                                    find = true;
                                    break;
                                }
                            }
                            if (!find) {
                                flag = false;
                            }
                        }
                    }

                    //插入衍生物信息到样本表
                    LimsSampleBean derivative = new LimsSampleBean();
                    derivative.setId(ApplicationContextHelper.getNextIdentity());
//                derivative.setSampleCode(ApplicationContextHelper.getNextSequence("T_LIMS_SAMPLE_DERIVATIVE", "SD"));
                    derivative.setSampleCode(derivaSampleCode);
                    derivative.setStatus("inExperiment");
                    derivative.setInHandle("3");
//                    derivative.setHandleType("wait");
                    derivative.setSampleType(sampleType.get());
                    derivative.setSampleTypeCode(sampleTypeCode);
                    derivative.setOriginalFlg("0");
                    derivative.setUseFlg(useFlg);
                    derivative.setParentNo(orderTaskBean.getSampleCode());
                    // 继承父样本的分院样本编号，实验样本编号
                    derivative.setHissampleCode(orderTaskBean.getExt$Item("HISSAMPLECODE"));
                    derivative.setExpNumber(orderTaskBean.getExt$Item("EXPNUMBER"));

                    derivative.setCreatedById(LocalContextHelper.getLoginUserId());
                    derivative.setCreatedByName(LocalContextHelper.getLoginUserName());
                    derivative.setCreatedByOrgId(LocalContextHelper.getLoginOrgId());
                    derivative.setCreatedByOrgName(LocalContextHelper.getLoginOrgName());
                    derivative.setCreatedTime(LocalDateTime.now());

                    //衍生物关系表
                    LimsSampleDerivativeBean sampleDerivativeBean = new LimsSampleDerivativeBean();
                    sampleDerivativeBean.setId(ApplicationContextHelper.getNextIdentity());
                    sampleDerivativeBean.setDerivativeId(derivative.getId());
                    sampleDerivativeBean.setDerivativeNo(derivative.getSampleCode());
                    sampleDerivativeBean.setParentNo(orderTaskBean.getSampleCode());
                    sampleDerivativeBean.setParentId(orderTaskBean.getSampleId());
                    sampleDerivativeBean.setOrderTaskId(orderTaskBean.getId());
                    sampleDerivativeBean.setFolderId(orderTaskBean.getFolderId());
                    sampleDerivativeBean.setOrderId(orderTaskBean.getOrderId());
                    sampleDerivativeBean.setDerivativeType(derivativeType);
                    sampleDerivativeBean.setUseFlag(useFlg);
                    sampleDerivativeBean.setExt$Item("parallelId", orderTaskBean.getParallelId().toString());

                    //原始样本
                    derivative.setOriNo(orderTaskBean.getExt$Item("oriNo"));
                    sampleDerivativeBean.setOriNo(orderTaskBean.getExt$Item("oriNo"));

                    //样本表
                    insertSampleList.add(derivative);
                    //衍生物表
                    insertSampleDerivativeList.add(sampleDerivativeBean);
                }
            }
        } else if ("mix".equalsIgnoreCase(derivativeType)) { // 混样
            String oriNo = orderTaskBeans.stream().map(t -> Arrays.asList(t.getExt$Item("oriNo").split(","))).flatMap(Collection::stream).distinct().collect(Collectors.joining(","));
            String parentNo = orderTaskBeans.stream().map(LimsOrderTaskBean::getSampleCode).distinct().collect(Collectors.joining(","));
            String oriHissampleCode = orderTaskBeans.stream().map(t -> Arrays.asList(t.getExt$Item("HISSAMPLECODE").split(","))).flatMap(Collection::stream).distinct().collect(Collectors.joining(","));
            String oriExpNumber = orderTaskBeans.stream().map(t -> Arrays.asList(t.getExt$Item("EXPNUMBER").split(","))).flatMap(Collection::stream).distinct().collect(Collectors.joining(","));
            String derivaSampleCode = null;

            //TODO  计算混样衍生物编码
            LimsOrderTaskBean first = orderTaskBeans.get(0);
            Collections.sort(sampleCodeList);
            List<LimsSampleDerivativeBean> mixDeri = this.selectListByFilter(SearchFilter.instance().match("parentId", first.getSampleId()).filter(MatchPattern.EQ).match("sampleTypeCode", sampleTypeCode).filter(MatchPattern.EQ).match("derivativeType", "mix").filter(MatchPattern.EQ));

            AtomicBoolean flag = new AtomicBoolean(false);
            int number = 0;
            for (LimsSampleDerivativeBean m : mixDeri) {
                List<String> sampleCodes = Arrays.stream(m.getOriNo().split(",")).collect(Collectors.toList());
                if (sampleCodes.size() == sampleCodeList.size()) {
                    Collections.sort(sampleCodes);
                    boolean same = true;
                    for (int i = 0; i < sampleCodeList.size(); i++) {
                        if (!sampleCodeList.get(i).equals(sampleCodes.get(i))) {
                            same = false;
                            break;
                        }
                    }
                    if (same) {
                        flag.set(true);
                        String[] parts = m.getDerivativeNo().split("-");
                        if (number == 0) {
                            if (parts.length > 1) {
                                number = Integer.parseInt(parts[1]) + 1;
                            }
                        } else {
                            if (parts.length > 1) {
                                number = (Integer.parseInt(parts[1]) + 1) > number ? (Integer.parseInt(parts[1]) + 1) : number;
                            }
                        }
                        derivaSampleCode = String.format("M%s%s-%d", typeBean.getBriefCode(), parts[0].substring(parts[0].indexOf("2"), parts[0].length()), number);
                    }
                }
            }
            if (!flag.get()) {
                derivaSampleCode = "M".concat(typeBean.getBriefCode()).concat(ApplicationContextHelper.getNextSequence("T_LIMS_SAMPLE_MIX")).concat("-1");
            }

            //插入衍生物信息到样本表
            LimsSampleBean derivative = new LimsSampleBean();
            derivative.setId(ApplicationContextHelper.getNextIdentity());
//            derivative.setSampleCode(ApplicationContextHelper.getNextSequence("T_LIMS_SAMPLE_DERIVATIVE", "MIX"));
            derivative.setSampleCode(derivaSampleCode);
            derivative.setStatus("inExperiment");
            derivative.setInHandle("3");
//            derivative.setHandleType("wait");
            derivative.setSampleTypeCode(sampleTypeCode);
            derivative.setSampleType(sampleType.get());
            derivative.setOriginalFlg("0");
            derivative.setUseFlg(useFlg);
            derivative.setParentNo(parentNo);
            derivative.setOriNo(oriNo);
            // 继承父样本的分院样本编号，实验样本编号
            derivative.setHissampleCode(oriHissampleCode);
            derivative.setExpNumber(oriExpNumber);
            derivative.setCreatedById(LocalContextHelper.getLoginUserId());
            derivative.setCreatedByName(LocalContextHelper.getLoginUserName());
            derivative.setCreatedByOrgId(LocalContextHelper.getLoginOrgId());
            derivative.setCreatedByOrgName(LocalContextHelper.getLoginOrgName());
            derivative.setCreatedTime(LocalDateTime.now());

            //样本表
            insertSampleList.add(derivative);
            for (LimsOrderTaskBean orderTaskBean : orderTaskBeans) {
                //衍生物关系表
                LimsSampleDerivativeBean sampleDerivativeBean = new LimsSampleDerivativeBean();
                sampleDerivativeBean.setId(ApplicationContextHelper.getNextIdentity());
                sampleDerivativeBean.setDerivativeId(derivative.getId());
                sampleDerivativeBean.setDerivativeNo(derivative.getSampleCode());
                sampleDerivativeBean.setParentNo(orderTaskBean.getSampleCode());
                sampleDerivativeBean.setParentId(orderTaskBean.getSampleId());
                sampleDerivativeBean.setOrderTaskId(orderTaskBean.getId());
                sampleDerivativeBean.setFolderId(orderTaskBean.getFolderId());
                sampleDerivativeBean.setOrderId(orderTaskBean.getOrderId());
                sampleDerivativeBean.setDerivativeType(derivativeType);
                sampleDerivativeBean.setOriNo(oriNo);
                sampleDerivativeBean.setUseFlag(useFlg);
                //衍生物表
                insertSampleDerivativeList.add(sampleDerivativeBean);
            }
        }

        //插入表
        if (!CollectionUtils.isEmpty(insertSampleList) && !CollectionUtils.isEmpty(insertSampleDerivativeList)) {
            sampleService.getDao().insert(insertSampleList);
            getDao().insert(insertSampleDerivativeList);
        }
    }

    @Override
    public List<LimsSampleBean> selectDerivativeInRunList(Long runId, RestJsonWrapperBean wrapperBean) {
        MapperParameter parameter = wrapperBean.extractMapFilter();
        parameter.put("runId", runId);
        return getDao().selectDerivativeList(parameter).parallelStream().map(e -> PersistableHelper.mapToPersistable(e, LimsSampleBean.class)).collect(Collectors.toList());
    }

    @Override
    public Page<LimsSampleDerivativeBean> selectMixTask(RestJsonWrapperBean wrapperBean) {
        return selectPagination(() -> getDao().selectMixTask(wrapperBean.extractMapFilter()), wrapperBean.extractPageRowBounds());
    }

    @Override
    @Transactional
    public void insertDerivativesMulti(RestJsonWrapperBean wrapper) {
        Map<String, String> parameter = wrapper.getParamMap();
        List<LimsOrderTaskBean> fromOrderTasks = wrapper.parse(LimsOrderTaskBean.class);
        if (fromOrderTasks.isEmpty()) {
            return;
        }
        fromOrderTasks = fromOrderTasks.stream().filter(o -> !StringUtils.isBlank(o.getGenerateDerivativeType())).collect(Collectors.toList());
        if (fromOrderTasks.isEmpty()) {
            return;
        }
        List<Long> parallelIds = fromOrderTasks.parallelStream().map(LimsOrderTaskBean::getParallelId).collect(Collectors.toList());
        MapperParameter temp = new MapperParameter();
        temp.setFilter(SearchFilter.instance().match("parallelId", parallelIds).filter(MatchPattern.OR));
        List<LimsOrderTaskBean> orderTaskBeans = orderTaskService.selectList(temp);
        List<LimsSampleTypeBean> sampleTypeAll = limsSampleTypeService.selectAll();

        String useFlg = Constant.YES;
        ArrayList<LimsSampleBean> insertSampleList = new ArrayList<>();
        ArrayList<LimsSampleDerivativeBean> insertSampleDerivativeList = new ArrayList<>();
        Map<String, List<LimsOrderTaskBean>> groupByGenerateDerivativeType = fromOrderTasks.stream().collect(Collectors.groupingBy(o -> o.getGenerateDerivativeType()));
        List<String> typeCodeAll = fromOrderTasks.stream().map(LimsOrderTaskBean::getDerivativeSampleTypeCode).collect(Collectors.toList());
        List<LimsSampleDerivativeBean> derivativeBeansAll = this.selectListByFilter(SearchFilter.instance().match("sampleTypeCode", typeCodeAll).filter(MatchPattern.OR));
        groupByGenerateDerivativeType.forEach((generateDerivativeType, tempList1) -> {
            if (StringUtils.equals(generateDerivativeType, "derivative")) {// 生成普通衍生物
                tempList1.forEach(od -> {
                    // 每条数据取到选的样本类型
                    String sampleTypeCode = od.getDerivativeSampleTypeCode();
                    if (!StringUtils.isBlank(sampleTypeCode)) {
                        AtomicReference<String> sampleType = new AtomicReference<>(sampleTypeCode);
                        sampleTypeAll.stream().filter(st -> st.getSampleTypeCode().equals(sampleTypeCode)).findAny().ifPresent(st -> {
                            sampleType.set(st.getSampleTypeName());
                        });
                        LimsSampleTypeBean typeBean = sampleTypeAll.stream().filter(t -> t.getSampleTypeCode().equals(sampleTypeCode)).findFirst().get();

                        List<Long> parallelIdList = new ArrayList<>();
                        // 根据paralleId查到关联的ordertask
                        List<LimsOrderTaskBean> parallelOrdertasks = orderTaskBeans.stream().filter(o -> o.getParallelId().equals(od.getParallelId())).collect(Collectors.toList());
                        for (LimsOrderTaskBean orderTaskBean : parallelOrdertasks) {

                            if (!insertSampleDerivativeList.isEmpty()) {
                                parallelIdList = insertSampleDerivativeList.stream().map(m -> NumberUtils.parseLong(m.getExt$Item("parallelId"))).distinct().collect(Collectors.toList());
                            }

                            String derivaSampleCode = null;
                            if (parallelIdList.contains(orderTaskBean.getParallelId())) {
                                //TODO 并行id相同的task 即为混样后任务  生成衍生物时公用一个衍生物编号，共用一个样本的id
            //                    derivaSampleCode = insertSampleDerivativeList.stream().filter(f -> orderTaskBean.getParallelId().equals(Long.parseLong(f.getExt$Item("parallelId")))).findFirst().get().getDerivativeNo();
                                insertSampleDerivativeList.stream().filter(f -> orderTaskBean.getParallelId().equals(Long.parseLong(f.getExt$Item("parallelId")))).findFirst().ifPresent(d -> {
                                    //衍生物关系表
                                    LimsSampleDerivativeBean sampleDerivativeBean = new LimsSampleDerivativeBean();
                                    sampleDerivativeBean.setId(ApplicationContextHelper.getNextIdentity());
                                    sampleDerivativeBean.setDerivativeId(d.getDerivativeId());
                                    sampleDerivativeBean.setDerivativeNo(d.getDerivativeNo());
                                    sampleDerivativeBean.setParentNo(orderTaskBean.getSampleCode());
                                    sampleDerivativeBean.setParentId(orderTaskBean.getSampleId());
                                    sampleDerivativeBean.setOrderTaskId(orderTaskBean.getId());
                                    sampleDerivativeBean.setFolderId(orderTaskBean.getFolderId());
                                    sampleDerivativeBean.setOrderId(orderTaskBean.getOrderId());
                                    sampleDerivativeBean.setDerivativeType(generateDerivativeType);
                                    sampleDerivativeBean.setUseFlag(useFlg);
                                    sampleDerivativeBean.setExt$Item("parallelId", orderTaskBean.getParallelId().toString());
                                    sampleDerivativeBean.setOriNo(orderTaskBean.getExt$Item("oriNo"));

                                    //衍生物表
                                    insertSampleDerivativeList.add(sampleDerivativeBean);
                                });
                            } else {
                                String startSampleCode = orderTaskBean.getSampleCode();
                                //衍生物首字母同父样本  包含混样样本M、质控样本N,P等
                                String firstCode = startSampleCode.substring(0, 1);

                                String[] parts = startSampleCode.split("-");
                                String sampleCodeFront = "";

                                String qcsampleflg = orderTaskBean.getExt$Item("qcsampleflg");

                                if (StringUtils.isBlank(qcsampleflg) || !"1".equals(qcsampleflg)) {
                                    if (parts.length > 1) {
                                        int index_1 = startSampleCode.indexOf("2");
                                        sampleCodeFront = String.format("%s%s%s", firstCode, typeBean.getBriefCode(), parts[0].substring(index_1, parts[0].length()));
                                    } else {
                                        sampleCodeFront = String.format("%s%s%s", firstCode, typeBean.getBriefCode(), parts[0].substring(1, parts[0].length()));
                                    }
                                } else {
                                    String qcBriefCode = parts[0].substring(0, 1);
                                    if (parts.length > 1) {
                                        int index_1 = startSampleCode.indexOf("2");
                                        sampleCodeFront = String.format("%s%s%s", qcBriefCode, typeBean.getBriefCode(), parts[0].substring(index_1, parts[0].length()));
                                    } else {
                                        sampleCodeFront = String.format("%s%s%s", qcBriefCode, typeBean.getBriefCode(), parts[0].substring(1, parts[0].length()));
                                    }
                                }
                                String finalSampleCodeFront = sampleCodeFront;
                                List<LimsSampleDerivativeBean> derivativeBeans = derivativeBeansAll.stream().filter(d -> !StringUtils.isBlank(d.getDerivativeNo()) && d.getDerivativeNo().contains(finalSampleCodeFront)).collect(Collectors.toList());
                                if (derivativeBeans.isEmpty()) {
                                    derivaSampleCode = sampleCodeFront + "-1";
                                    int max = 1;
                                    boolean flag = true;
                                    while (flag) {
                                        boolean find = false;
                                        for (LimsSampleBean s : insertSampleList) {
                                            if (s.getSampleCode().equals(derivaSampleCode)) {
                                                max++;
                                                derivaSampleCode = sampleCodeFront + "-" + max;
                                                find = true;
                                                break;
                                            }
                                        }
                                        if (!find) {
                                            flag = false;
                                        }
                                    }
                                } else {
                                    int max = 1;
                                    for (LimsSampleDerivativeBean d : derivativeBeans) {
                                        String derivativeNo = d.getDerivativeNo();
                                        String[] parts_2 = derivativeNo.split("-");
                                        if (parts_2.length > 1 && Integer.parseInt(parts_2[1]) > max) {
                                            max = Integer.parseInt(parts_2[1]);
                                        }
                                    }
                                    max++;
                                    derivaSampleCode = sampleCodeFront + "-" + max;
                                    boolean flag = true;
                                    while (flag) {
                                        boolean find = false;
                                        for (LimsSampleBean s : insertSampleList) {
                                            if (s.getSampleCode().equals(derivaSampleCode)) {
                                                max++;
                                                derivaSampleCode = sampleCodeFront + "-" + max;
                                                find = true;
                                                break;
                                            }
                                        }
                                        if (!find) {
                                            flag = false;
                                        }
                                    }
                                }

                                //插入衍生物信息到样本表
                                LimsSampleBean derivative = new LimsSampleBean();
                                derivative.setId(ApplicationContextHelper.getNextIdentity());
                                derivative.setSampleCode(derivaSampleCode);
//                            derivative.setSampleCode(ApplicationContextHelper.getNextSequence("T_LIMS_SAMPLE_DERIVATIVE", "SD"));
                                derivative.setStatus("inExperiment");
                                derivative.setInHandle("3");
//                                derivative.setHandleType("wait");
                                derivative.setSampleType(sampleType.get());
                                derivative.setSampleTypeCode(sampleTypeCode);
                                derivative.setOriginalFlg("0");
                                derivative.setUseFlg(useFlg);
                                derivative.setParentNo(orderTaskBean.getSampleCode());
                                // 继承父样本的分院样本编号，实验样本编号
                                derivative.setHissampleCode(orderTaskBean.getExt$Item("HISSAMPLECODE"));
                                derivative.setExpNumber(orderTaskBean.getExt$Item("EXPNUMBER"));
                                derivative.setCreatedById(LocalContextHelper.getLoginUserId());
                                derivative.setCreatedByName(LocalContextHelper.getLoginUserName());
                                derivative.setCreatedByOrgId(LocalContextHelper.getLoginOrgId());
                                derivative.setCreatedByOrgName(LocalContextHelper.getLoginOrgName());
                                derivative.setCreatedTime(LocalDateTime.now());

                                //衍生物关系表
                                LimsSampleDerivativeBean sampleDerivativeBean = new LimsSampleDerivativeBean();
                                sampleDerivativeBean.setId(ApplicationContextHelper.getNextIdentity());
                                sampleDerivativeBean.setDerivativeId(derivative.getId());
                                sampleDerivativeBean.setDerivativeNo(derivative.getSampleCode());
                                sampleDerivativeBean.setParentNo(orderTaskBean.getSampleCode());
                                sampleDerivativeBean.setParentId(orderTaskBean.getSampleId());
                                sampleDerivativeBean.setOrderTaskId(orderTaskBean.getId());
                                sampleDerivativeBean.setFolderId(orderTaskBean.getFolderId());
                                sampleDerivativeBean.setOrderId(orderTaskBean.getOrderId());
                                sampleDerivativeBean.setDerivativeType(generateDerivativeType);
                                sampleDerivativeBean.setUseFlag(useFlg);
                                sampleDerivativeBean.setExt$Item("parallelId", orderTaskBean.getParallelId().toString());

                                //原始样本
                                derivative.setOriNo(orderTaskBean.getExt$Item("oriNo"));
                                sampleDerivativeBean.setOriNo(orderTaskBean.getExt$Item("oriNo"));

                                //样本表
                                insertSampleList.add(derivative);
                                //衍生物表
                                insertSampleDerivativeList.add(sampleDerivativeBean);
                            }
                        }
                    }
                });
            } else if (StringUtils.equals(generateDerivativeType, "mix")) {// 生成混样衍生物
                // 根据混样序号分组
                Map<String, List<LimsOrderTaskBean>> groupByMixGroupId = tempList1.stream().filter(o -> !StringUtils.isBlank(o.getMixGroupId())).collect(Collectors.groupingBy(o -> o.getMixGroupId()));
                groupByMixGroupId.forEach((groupId, tempList2) -> {
                    // 参与混样的数目要大于1
                    if (tempList2.size() > 1) {
                        // 同一个混样序号下面的混样样本类型只能有一个
                        List<String> distinctSampleType = tempList2.stream().map(o -> o.getDerivativeSampleTypeCode()).distinct().collect(Collectors.toList());
                        if (!distinctSampleType.isEmpty() && distinctSampleType.size() == 1) {
                            // 混样类型
                            String sampleTypeCode = tempList2.get(0).getDerivativeSampleTypeCode();
                            List<String> sampleCodeList = tempList2.stream().map(LimsOrderTaskBean::getSampleCode).distinct().collect(Collectors.toList());
                            if (!StringUtils.isBlank(sampleTypeCode)) {
                                AtomicReference<String> sampleType = new AtomicReference<>(sampleTypeCode);
                                sampleTypeAll.stream().filter(st -> st.getSampleTypeCode().equals(sampleTypeCode)).findAny().ifPresent(st -> {
                                    sampleType.set(st.getSampleTypeName());
                                });
                                LimsSampleTypeBean typeBean = sampleTypeAll.stream().filter(t -> t.getSampleTypeCode().equals(distinctSampleType.get(0))).findFirst().get();

                                // 取到能参与混样的ordertask的关联数据
                                List<Long> tempParalleIds = tempList2.stream().map(LimsOrderTaskBean::getParallelId).distinct().collect(Collectors.toList());
                                List<LimsOrderTaskBean> tempList3 = orderTaskBeans.stream().filter(o -> tempParalleIds.contains(o.getParallelId())).collect(Collectors.toList());

                                String oriNo = tempList3.stream().map(t -> Arrays.asList(t.getExt$Item("oriNo").split(","))).flatMap(Collection::stream).distinct().collect(Collectors.joining(","));
                                String parentNo = tempList3.stream().map(LimsOrderTaskBean::getSampleCode).distinct().collect(Collectors.joining(","));
                                String oriHissampleCode = tempList3.stream().map(t -> Arrays.asList(t.getExt$Item("HISSAMPLECODE").split(","))).flatMap(Collection::stream).distinct().collect(Collectors.joining(","));
                                String oriExpNumber = tempList3.stream().map(t -> Arrays.asList(t.getExt$Item("EXPNUMBER").split(","))).flatMap(Collection::stream).distinct().collect(Collectors.joining(","));
                                String derivaSampleCode = null;

                                //TODO  计算混样衍生物编码
                                LimsOrderTaskBean first = orderTaskBeans.get(0);
                                Collections.sort(sampleCodeList);
                                List<LimsSampleDerivativeBean> mixDeri = this.selectListByFilter(SearchFilter.instance().match("parentId", first.getExt$Item("sampleId")).filter(MatchPattern.EQ).match("sampleTypeCode", sampleTypeCode).filter(MatchPattern.EQ).match("derivativeType", "mix").filter(MatchPattern.EQ));

                                AtomicBoolean flag = new AtomicBoolean(false);
                                int number = 0;
                                for (LimsSampleDerivativeBean m : mixDeri) {
                                    List<String> sampleCodes = Arrays.stream(m.getOriNo().split(",")).collect(Collectors.toList());
                                    if (sampleCodes.size() == sampleCodeList.size()) {
                                        Collections.sort(sampleCodes);
                                        boolean same = true;
                                        for (int i = 0; i < sampleCodeList.size(); i++) {
                                            if (!sampleCodeList.get(i).equals(sampleCodes.get(i))) {
                                                same = false;
                                                break;
                                            }
                                        }
                                        if (same) {
                                            flag.set(true);
                                            String[] parts = m.getDerivativeNo().split("-");
                                            if (number == 0) {
                                                if (parts.length > 1) {
                                                    number = Integer.parseInt(parts[1]) + 1;
                                                }
                                            } else {
                                                if (parts.length > 1) {
                                                    number = (Integer.parseInt(parts[1]) + 1) > number ? (Integer.parseInt(parts[1]) + 1) : number;
                                                }
                                            }
                                            derivaSampleCode = String.format("M%s%s-%d", typeBean.getBriefCode(), parts[0].substring(parts[0].indexOf("2"), parts[0].length()), number);
                                        }
                                    }
                                }
                                if (!flag.get()) {
                                    derivaSampleCode = "M".concat(typeBean.getBriefCode()).concat(ApplicationContextHelper.getNextSequence("T_LIMS_SAMPLE_MIX")).concat("-1");
                                }

                                //插入衍生物信息到样本表
                                LimsSampleBean derivative = new LimsSampleBean();
                                derivative.setId(ApplicationContextHelper.getNextIdentity());
                                derivative.setSampleCode(derivaSampleCode);
//                                derivative.setSampleCode(ApplicationContextHelper.getNextSequence("T_LIMS_SAMPLE_DERIVATIVE", "MIX"));
                                derivative.setStatus("inExperiment");
                                derivative.setInHandle("3");
//                                derivative.setHandleType("wait");
                                derivative.setSampleTypeCode(sampleTypeCode);
                                derivative.setSampleType(sampleType.get());
                                derivative.setOriginalFlg("0");
                                derivative.setUseFlg(useFlg);
                                derivative.setParentNo(parentNo);
                                derivative.setOriNo(oriNo);
                                // 继承父样本的分院样本编号，实验样本编号
                                derivative.setHissampleCode(oriHissampleCode);
                                derivative.setExpNumber(oriExpNumber);
                                //样本表
                                insertSampleList.add(derivative);
                                for (LimsOrderTaskBean orderTaskBean : orderTaskBeans) {
                                    //衍生物关系表
                                    LimsSampleDerivativeBean sampleDerivativeBean = new LimsSampleDerivativeBean();
                                    sampleDerivativeBean.setId(ApplicationContextHelper.getNextIdentity());
                                    sampleDerivativeBean.setDerivativeId(derivative.getId());
                                    sampleDerivativeBean.setDerivativeNo(derivative.getSampleCode());
                                    sampleDerivativeBean.setParentNo(orderTaskBean.getSampleCode());
                                    sampleDerivativeBean.setParentId(orderTaskBean.getSampleId());
                                    sampleDerivativeBean.setOrderTaskId(orderTaskBean.getId());
                                    sampleDerivativeBean.setFolderId(orderTaskBean.getFolderId());
                                    sampleDerivativeBean.setOrderId(orderTaskBean.getOrderId());
                                    sampleDerivativeBean.setDerivativeType(generateDerivativeType);
                                    sampleDerivativeBean.setOriNo(oriNo);
                                    sampleDerivativeBean.setUseFlag(useFlg);
                                    //衍生物表
                                    insertSampleDerivativeList.add(sampleDerivativeBean);
                                }
                            }
                        }
                    }
                });
            }
        });

//        LimsSampleTypeBean sampleTypeBean = sampleTypeService.selectFirstByFilter(SearchFilter.instance().match("sampleTypeCode", sampleType).filter(MatchPattern.EQ));
//        String sampleTypeName = sampleTypeBean.getSampleTypeName();
//        String briefCode = sampleTypeBean.getBriefCode();
//        if (StringUtils.isEmpty(briefCode)){//样本类型简码
//            throw new InvalidDataException(I18nHelper.getMessage("NOT.FOUND.SAMPLE.BRIEFCODE")+"【"+sampleTypeName+"】");
//        }
//        List<Long> orderTaskIdList = orderTaskBeans.stream().map(LimsOrderTaskBean::getId).collect(Collectors.toList());
        // 原有衍生物，则新衍生物不启用
//        List<LimsSampleDerivativeBean> sampleDerivativeList = selectListByFilter(SearchFilter.instance().match("ORDERTASKID", orderTaskIdList).filter(MatchPattern.OR));
//        if (!sampleDerivativeList.isEmpty()) {
//            useFlg = Constant.NO;
//        }

        //插入表
        if (!CollectionUtils.isEmpty(insertSampleList) && !CollectionUtils.isEmpty(insertSampleDerivativeList)) {
            sampleService.getDao().insert(insertSampleList);
            getDao().insert(insertSampleDerivativeList);
        }
    }
}
